package generateConnections;

import java.util.ArrayList;

import exception.NoConnectionPossibleException;

import networkInterface.NetworkInterfaceBase;

import logging.Logger;

import object.Node;
import util.NodeUtil;
import util.Settings;
import util.ShuffleUtil;

public class GenerateLargeNetwork extends GenerateConnectionBase {

	
	/* This connection algorithm is meant to connect a node to the biggest network it can
	 * by connection it to the largest network first. It will then connect the node to
	 * any other smaller networks in its range (therefore combining two networks) If 
	 * interfaces are still available, they will create connections to random nodes in the area
	 * */
	@Override
	public void genConnections(ArrayList<Node> nodes, Node node) {
		Logger.getInstance().log(Logger.TRACE, "Connecting node to the largest available network");
		
		
		NetworkInterfaceBase bestInterface = null;
		NetworkInterfaceBase altInterface = null;
		ArrayList<Node> hold1 = new ArrayList<Node>();
		ArrayList<Node> hold2 = new ArrayList<Node>();
		for( NetworkInterfaceBase connectingInterface : node.getInterfaces() )
		{
			ArrayList<NetworkInterfaceBase> possibleInterfaces = connectingInterface.getConnectableInterfaces(nodes);
			//while( !possibleInterfaces.isEmpty() )
			//{
				bestInterface = null;
				altInterface = null;
				Logger.getInstance().log(Logger.TRACE, "Found " + possibleInterfaces.size() + " possible interfaces");
				for( NetworkInterfaceBase i: possibleInterfaces )
				{
					hold1.clear();
					NodeUtil.mapNetwork(node, hold1);
										
					if( hold1.contains(i.getNode()) )
					{
						altInterface = i;
						continue;
					}
					hold1.clear();
					if( bestInterface == null || NodeUtil.mapNetwork(bestInterface.getNode(), hold1) < NodeUtil.mapNetwork(i.getNode(), hold2))
					{
						Logger.getInstance().log(Logger.TRACE, "Found new best Interface");
						bestInterface = i;
					}
				}
				if( bestInterface != null )
				{
					try { 
						Logger.getInstance().log(Logger.TRACE, "Adding Connection to best interface");
						connectingInterface.addConnection(bestInterface);	
					} 
					catch (IllegalStateException e) {
						Logger.getInstance().log(Logger.WARNING, "Reached an unpleasant state while attemtping to connect to the best interface");
					} 
					catch (NoConnectionPossibleException e) {
						Logger.getInstance().log(Logger.WARNING, "Could not create a connection to the best interface");
					}
				}
				else if( altInterface != null )
				{
					try { 
						Logger.getInstance().log(Logger.TRACE, "Adding Connection to alternate interface");
						connectingInterface.addConnection(altInterface);	
					} 
					catch (IllegalStateException e) {
						Logger.getInstance().log(Logger.WARNING, "Reached an unpleasant state while attemtping to connect to the best interface");
					} 
					catch (NoConnectionPossibleException e) {
						Logger.getInstance().log(Logger.WARNING, "Could not create a connection to the best interface");
					}
				}
				else
					Logger.getInstance().log(Logger.WARNING, "Could not create a connection from this interface for unknow reasons");
				
				possibleInterfaces.clear();
				possibleInterfaces = connectingInterface.getConnectableInterfaces(nodes);
			//}
		}
		
	}
	

}
